var XMPP_HOST = 'zy48';
var BOSH_SERVICE = 'http://48.lsu.pw:7070/http-bind/';
var connection;

var myName;
var myJid;
var myPasswd;
var peerJid;
var siteCode;
var logLevel;

var xmppPres = {};
xmppPres.offline = 'offline';
xmppPres.waiting = 'waiting';
xmppPres.chating = 'chating';
xmppPres.afterChat = 'after';

/**
 * Generate unique id like ->
 *   "bfc7d682_c7f2e1ed_ab0c0193_63b53085"
 *
 * @Source http://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript?page=1&tab=votes#answer-105074
 * @return unique id.
 */
function guid() {
  function s4() {
    return Math.floor((1 + Math.random()) * 0x10000)
        .toString(16)
        .substring(1);
  }

  return s4() + s4() + '_' + s4() + s4() + '_' +
      s4() + s4() + '_' + s4() + s4();
};


function consoleLog(mess, level) {
  if (level <= logLevel) {
    console.log('log level ' + level + ': ' + mess);
  }
}
/***********************************************************************************************************************
 *
 * DOM functions.
 *
 **********************************************************************************************************************/

function openChatpanel() {
  $('.chat_panel').fadeIn();
};

function hideChatPanel() {
  $('.chat_panel').hide();
};

function showBeginChatPrompt() {
  $('#begin_chat_prompt').show();
};

function hideBeginChatPrompt() {
  $('#begin_chat_prompt').hide();
};


/***********************************************************************************************************************
 *
 * XMPP functions.
 *
 **********************************************************************************************************************/

function getBareJid(fullJid) {
  var idx = fullJid.search('/');
  if (idx >= 0) {
    idx = fullJid.substr(0, idx);
  }
  return idx;
}

function askSubscribe(pureJid) {
  consoleLog('ask subscribe to ' + pureJid, 1);
  connection.send($pres({to: pureJid, type: 'subscribe'}).tree());
  subscribedTo(pureJid);
}

function subscribedTo(pureJid) {
  consoleLog('subscribed to ' + pureJid);
  connection.send($pres({to: pureJid, type: 'subscribed'}).tree());
}


function onRosterLeave(pres) {
  var roster = pres.getAttribute('from');
}


function searchService() {
  connection.send($iq({'type': 'set', 'to': 'search.' + XMPP_HOST})
      .cnode(Strophe.xmlElement('query', {'xmlns': 'jabber:iq:search'}))
      .cnode(Strophe.xmlElement('x', {'xmlns': 'jabber:x:data', 'type': 'submit'}))
      .cnode(Strophe.xmlElement('field', {'var': 'FORM_TYPE', type: 'hidden'}))
      .cnode(Strophe.xmlElement('value', 'jabber:iq:search')).up().up()
      .cnode(Strophe.xmlElement('field', {var: 'search'}))
      .cnode(Strophe.xmlElement('value', '-service-' + siteCode))
      .up().up().cnode(Strophe.xmlElement('field', {'var': 'Email'}))
      .cnode(Strophe.xmlElement('value', '1'))
      .up().up().cnode(Strophe.xmlElement('field', {'var': 'Username'}))
      .cnode(Strophe.xmlElement('value', '1'))
      .up().up().cnode(Strophe.xmlElement('field', {'var': 'Name'}))
      .cnode(Strophe.xmlElement('value', '1'))
      .tree());
}

function login(jid, passwd) {
  consoleLog('login with ' + jid + ', ' + passwd);
  connection.connect(jid,
      passwd,
      onConnect);
};

function onSearchResult(iq) {
  var items = iq.getElementsByTagName('item');
  for (i = 0; i < items.length; i++) {
    var item = items[i];
    var fields = item.getElementsByTagName('field');
    for (j = 0; j < fields.length; j++) {
      var field = fields[j];
      if (field.getAttribute('var') == 'jid') {
        var value = field.getElementsByTagName(value);
        var jid = Strophe.getText(value);
        consoleLog('searched: ' + jid);
        askSubscribe(jid);
      }
    }
  }
}

function onMessage(msg) {
  var to = msg.getAttribute('to');
  var from = msg.getAttribute('from');
  var type = msg.getAttribute('type');
  var elems = msg.getElementsByTagName('body');

  if (type == "chat" && elems.length > 0) {
    appendTextMessage(1, Strophe.getText(msg.getElementsByTagName('body')[0]));
  }
  return true;
}

function onPresence(pres) {
  var presType = pres.getAttribute('type');
  if (presType == 'subscribe') {
    onSubscribe(pres);
    return;
  }
  if (presType == 'unavailable') {
    onRosterLeave(pres);
  }
  var from = pres.getAttribute('from');
  if (from.search('-custom-') >= 0) {
    var prefixName = from.substr(0, 35);
    var status = pres.getElementsByTagName('status');
    if (status.length > 0) {
      updateCustomItem(from);
      status = Strophe.getText(status[0]);
    }
  }
}

/**
 * Show text message on chat board.
 *
 * @param messageSource the sender of the message, 1 for peer, 2 for self. TODO: 3 for notify.
 */
function appendTextMessage(messageSource, textMessage) {
  var container = document.createElement('div');
  var paragraph = document.createElement('p');
  paragraph.innerHTML = textMessage;
  $(container).append(paragraph);
  if (messageSource == 1) {
    $(container).addClass("chat_message_in");
  } else if (messageSource == 2) {
    $(container).addClass("chat_message_out");
  }
  $('.chat_panel_message_board').append(container);
  messageBoardScrollToBottom($('.chat_panel_message_board'));
}

$(document).ready(function () {
  logLevel = 3;
  //var siteCode = new RegExp(".{8}\$").exec(location.pathname)[0];
  siteCode = 'ab74a03a';
  connection = new Strophe.Connection(BOSH_SERVICE);

  myPasswd = localStorage.getItem('myPasswd');
  myName = localStorage.getItem('myName-' + siteCode);
  if (!myName) {
    myName = guid() + '-custom-' + siteCode;
    localStorage.setItem('myName-' + siteCode, myName);
    myJid = myName + '@' + XMPP_HOST;
    if (!myPasswd) {
      myPasswd = guid();
      localStorage.setItem('myPasswd', myPasswd);
    }
    connection.register.connect(XMPP_HOST, onConnect);
  } else {
    myJid = myName + '@' + XMPP_HOST;
    login(myJid, myPasswd);
  }
  searchService();
  showBeginChatPrompt();

  $('body').on('click', '#begin_chat_button', function () {
    hideBeginChatPrompt();
    openChatpanel();
  });

  $('body').on('click', '.close-chat-panle-button', function () {
    hideChatPanel();
    sendPresence(xmppPres.after);
    showBeginChatPrompt();
  });

  /**
   * Called on send button clicked.
   */
  $('body').on('click', '.send-button', function () {
    var message = $('.chat_panel_send_board_input').val();
    sendChatMessage(peerJid, message);
    appendTextMessage(2, message);
    $('.chat_panel_send_board_input').val("");
  });
});